#ifndef SKIP_LIST_ON_RAFT_KVSERVER_H
#define SKIP_LIST_ON_RAFT_KVSERVER_H

// 依赖库：boost序列化库（用于快照的序列化/反序列化）
#include <boost/any.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/foreach.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/unordered_map.hpp>
#include <boost/serialization/vector.hpp>
#include <iostream>
#include <mutex>  // 互斥锁，用于线程安全
#include <unordered_map>
#include "kvServerRPC.pb.h"  // Protobuf生成的RPC接口定义
#include "raft.h"  // Raft共识算法接口
#include "skipList.h"  // 跳表数据结构（底层KV存储）

// KvServer类：实现基于Raft的分布式KV服务，继承自Protobuf生成的RPC服务基类
class KvServer : raftKVRpcProctoc::kvServerRpc {
private:
    std::mutex m_mtx;   // 互斥锁，保护KV数据操作的线程安全（多线程环境下）
    int m_me;           // 当前KV服务器的节点ID（在Raft集群中的标识）
    std::shared_ptr<raftCore::Raft> m_raftNode;  // Raft节点实例指针，用于与Raft集群交互（提交日志、达成共识）
    // 通信管道：接收Raft节点提交的日志条目（已达成共识的操作），KV服务器需应用这些操作到本地状态机
    std::shared_ptr<common::LockQueue<raftCore::ApplyMsg>> applyChan;  
    int m_maxRaftState;  // Raft日志大小阈值：当日志超过该值时，触发快照生成（减少日志存储）

    // KV存储相关
    std::string m_serializedKVData;  // 序列化后的KV数据（临时用于快照，后续可能优化）
    SkipList<std::string, std::string> m_skipList;  // 跳表：核心KV存储结构（支持高效查找、插入、删除）
    // std::unordered_map<std::string, std::string> m_kvDB;  // 哈希表：可能作为辅助存储（或临时调试用，需结合实现判断）

    // 等待队列映射：键为Raft日志索引，值为等待该日志提交的操作队列
    // 用于客户端请求发送后，等待Raft将操作提交后再返回结果
    std::unordered_map<int, common::LockQueue<common::Op>*> waitApplyCh;  

    // 客户端请求去重：记录每个客户端（ClientId）的最后一次请求ID（RequestId）
    // 防止客户端重试导致的重复执行（保证操作幂等性）
    std::unordered_map<std::string, int> m_lastRequestId;  

    // 最后一次快照对应的Raft日志索引（用于快照的版本管理，避免重复安装旧快照）
    int m_lastSnapShotRaftLogIndex;

public:
    // 参数：me（节点ID）、maxraftstate（快照触发阈值）、nodeInforFileName（节点信息文件）、port（RPC服务端口）
    KvServer(int me, int maxraftstate, std::string nodeInforFileName, short port);

    void DprintfKVDB();  // 调试用：打印当前KV数据库的内容

    // 应用Raft提交的操作到本地KV存储
    void ExecuteAppendOpOnKVDB(common::Op op);  // 执行Append操作（向某个键追加值）
    void ExecuteGetOpOnKVDB(common::Op op, std::string *value, bool *exist);  // 执行Get操作（查询键值）
    void ExecutePutOpOnKVDB(common::Op op);  // 执行Put操作（设置键值）

    // 处理客户端请求的内部方法（非RPC接口，用于逻辑封装）
    // GetArgs/PutAppendArgs：客户端请求参数；reply：返回给客户端的结果
    void Get(const raftKVRpcProctoc::GetArgs *args, raftKVRpcProctoc::GetReply *reply);
    /**
     * 从Raft节点获取已提交的日志消息（即需要应用到KV存储的操作）
     * @param message Raft传来的已提交日志（ApplyMsg类型，包含操作内容）
     */
    void GetCommandFromRaft(raftCore::ApplyMsg message);

    // 检查客户端请求是否重复（根据ClientId和RequestId）
    bool ifRequestDuplicate(std::string ClientId, int RequestId);

    // 处理客户端的Put/Append请求（内部逻辑，非RPC接口）
    void PutAppend(const raftKVRpcProctoc::PutAppendArgs *args, raftKVRpcProctoc::PutAppendReply *reply);

    // 循环读取Raft提交的日志并应用到KV存储
    // 核心逻辑：从applyChan中获取消息，调用Execute*OpOnKVDB执行操作
    void ReadRaftApplyCommandLoop();

    // 从快照数据中恢复KV存储（当收到Raft发送的快照时调用）
    void ReadSnapShotToInstall(std::string snapshot);

    // 向等待队列发送消息（通知操作已完成）
    // 参数：op（已执行的操作）、raftIndex（该操作对应的Raft日志索引）
    bool SendMessageToWaitChan(const common::Op &op, int raftIndex);

    // 检查是否需要生成快照：当Raft日志大小超过阈值时，触发快照并发送给Raft
    // 参数：raftIndex（当前日志索引）、proportion（快照大小比例阈值，辅助判断）
    void IfNeedToSendSnapShotCommand(int raftIndex, int proportion);

    // 处理从Raft传来的快照（如Leader发送的快照，用于同步落后的节点）
    void GetSnapShotFromRaft(raftCore::ApplyMsg message);

    // 生成当前KV存储的快照数据（序列化后返回）
    std::string MakeSnapShot();

public:  // RPC服务接口实现（Protobuf定义的远程调用接口）
    // 实现客户端的Put/Append远程调用
    void PutAppend(google::protobuf::RpcController *controller, const ::raftKVRpcProctoc::PutAppendArgs *request,
                 ::raftKVRpcProctoc::PutAppendReply *response, ::google::protobuf::Closure *done) override;

    // 实现客户端的Get远程调用
    void Get(google::protobuf::RpcController *controller, const ::raftKVRpcProctoc::GetArgs *request,
           ::raftKVRpcProctoc::GetReply *response, ::google::protobuf::Closure *done) override;

private:
    ///////////////// 序列化相关（用于快照） ///////////////////////////////
    // 允许boost序列化库访问私有成员（用于快照的序列化/反序列化）
    friend class boost::serialization::access;

    // 序列化方法：定义需要写入快照的字段
    template <class Archive>
    void serialize(Archive &ar, const unsigned int version) {
        ar &m_serializedKVData; // 序列化KV数据（临时字段）
        ar &m_lastRequestId;    // 序列化客户端请求去重信息（保证快照恢复后仍能去重）
    }

    // 生成快照数据：将当前KV状态（跳表）序列化，结合其他必要信息生成快照字符串
    std::string getSnapshotData() {
        m_serializedKVData = m_skipList.dump_file();  // 先序列化跳表数据
        std::stringstream ss;
        boost::archive::text_oarchive oa(ss);  // 使用文本归档器序列化当前对象
        oa << *this;
        m_serializedKVData.clear();  // 清空临时字段
        return ss.str();  // 返回完整快照数据
    }

    // 从快照字符串解析数据并恢复KV状态
    void parseFromString(const std::string &str) {
        std::stringstream ss(str);
        boost::archive::text_iarchive ia(ss);  // 文本解归档器
        ia >> *this;  // 反序列化对象
        m_skipList.load_file(m_serializedKVData);  // 恢复跳表数据
        m_serializedKVData.clear();  // 清空临时字段
    }

};

#endif  // SKIP_LIST_ON_RAFT_KVSERVER_H